package geochallenge

import (
    "encoding/json"
    "net/http"

    "appengine"
    "appengine/datastore"
)

type Challenge struct {
    Title  string
    Content []byte
}

type ChallengeInfo struct {
    Title string
    Id string
}

type CreateChallengeMessage struct {
    Title string
    Content string
}

func init() {
    http.HandleFunc("/challenge", challenge)
    http.HandleFunc("/challenges", challenges)
}

// guestbookKey returns the key used for all guestbook entries.
// func guestbookKey(c appengine.Context) *datastore.Key {
//         // The string "default_guestbook" here could be varied to have multiple guestbooks.
//         return datastore.NewKey(c, "Guestbook", "default_guestbook", 0, nil)
// }

func challenges(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    c := appengine.NewContext(r)
    // Ancestor queries, as shown here, are strongly consistent with the High
    // Replication Datastore. Queries that span entity groups are eventually
    // consistent. If we omitted the .Ancestor from this query there would be
    // a slight chance that Greeting that had just been written would not
    // show up in a query.
    // [START query]
    q := datastore.NewQuery("Challenge").Limit(100)
    // [END query]
    // [START getall]
    var challenges []Challenge
    keys, err := q.GetAll(c, &challenges)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    var result []ChallengeInfo
    for i, ch := range challenges {
        chi := ChallengeInfo {
            Title: ch.Title,
            Id: keys[i].Encode(),
        }
        result = append(result, chi)
    }
    b, _ := json.Marshal(result)
    w.Write(b)
}

func challenge(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    if r.Method == "POST" {
        err := createChallenge(w, r)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
    } else if r.Method == "GET" {
        err := fetchChallenge(w, r)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
    }
    w.WriteHeader(http.StatusOK)
}

func createChallenge(w http.ResponseWriter, r *http.Request) error {
    dec := json.NewDecoder(r.Body)
    var msg CreateChallengeMessage
    err := dec.Decode(&msg)
    if err != nil {
        return err
    }
    ch := Challenge {
        Title: msg.Title,
        Content: []byte(msg.Content),
    }
    c := appengine.NewContext(r)
    key := datastore.NewIncompleteKey(c, "Challenge", nil)
    newKey, err := datastore.Put(c, key, &ch)
    if err != nil {
        return err
    }
    w.Write([]byte(newKey.Encode()))
    return err
}

func fetchChallenge(w http.ResponseWriter, r *http.Request) error {
    id := r.FormValue("id")
    c := appengine.NewContext(r)
    key, err := datastore.DecodeKey(id)
    if err != nil {
        return err
    }
    var ch Challenge
    err = datastore.Get(c, key, &ch)
    if err != nil {
        return err
    }
    w.Write(ch.Content)
    return err
}
